﻿using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;

namespace XMLParser
{
    class Program
    {
        //1. Elements with children Elements or attributes go as Class in seperate file
        //2. All attributes go as Data Members
        //3. All Children Elements w/o children go as data members
        //    if Single as DataType
        //    else as ListofString

        static void Main(string[] args)
        {
            //String xmlFile = @"C:\Raman\code\CodeGen\fmpp_0.9.14\docs\examples\xml\src\data\test.xml";
            String xmlFile = @"C:\Raman\code\C++\XMLParserGen\CodeProject\rss.xml";
            //String xmlFile = @"C:\Raman\code\C++\XMLParserGen\XSDE\xsde-3.2.0-i686-windows\examples\cxx\parser\generated\library.xml";
            //String xmlFile = @"C:\Raman\code\C++\XMLParserGen\XSDE\xsde-3.2.0-i686-windows\examples\cxx\hybrid\wildcard\email.xml";

            XmlDocument doc = new XmlDocument();
            doc.Load(xmlFile);

            System.Xml.XmlElement root = doc.DocumentElement;

            ClassObject rootClass = PrintChildren(root, "", null);

            rootClass.Debug("");

            // create reader & open file
            TextReader tr = new StreamReader(@"C:\Raman\code\CodeGen\CodePatterns\tdd\xml\Class.h");

            string strTemplate = tr.ReadToEnd();
            tr.Close();

            rootClass.Stream( @"C:\Raman\code\CodeGen\CodePatterns\tdd\xml\src", strTemplate );

            tr = new StreamReader(@"C:\Raman\code\CodeGen\CodePatterns\tdd\xml\Writer.cpp");
            strTemplate = tr.ReadToEnd();
            tr.Close();

            Writer writer = new Writer( rootClass );
            writer.Stream( xmlFile, @"C:\Raman\code\CodeGen\CodePatterns\tdd\xml\src", strTemplate );
            //return;

            tr = new StreamReader( @"C:\Raman\code\CodeGen\CodePatterns\tdd\xml\Parser.cpp" );
            strTemplate = tr.ReadToEnd();
            tr.Close();

            Parser parser = new Parser( rootClass );

            parser.Stream( "Rss", @"C:\Raman\code\CodeGen\CodePatterns\tdd\xml\src", strTemplate );

        }

        static ClassObject PrintChildren(XmlElement node, String tab, ClassObject parentClass)
        {
            String val = String.Empty ;
            if ( null != node.Value)
            {
                val = " Value : " + node.Value;
            }

            System.Console.WriteLine(tab + "Parsing Node : " + node.Name + " Type : " + node.NodeType + val);

            //1. Elements with children Elements or attributes go as Class in seperate file
            //2. All attributes go as Data Members
            //3. All Children Elements w/o children go as data members
            //    if Single as DataType
            //    else as ListofString

            ClassObject obj = null;
            if (node.HasAttributes)
            {
                obj = new ClassObject( node.Name, null, "element" );
                foreach (XmlAttribute attr in node.Attributes)
                {
                    attr.Value.Trim();
                    attr.Name.Trim() ;

                    System.Console.WriteLine(tab + "Name : " + attr.Name + " Value : " + attr.Value);
                    decimal decimalNum = 0;
                    int number1 = 0;
                    Attribute attrib = null;
                    if( int.TryParse( attr.Value, out number1 ) )
                        attrib = new Attribute( attr.Name, "int", attr.Value, "attr" );
                    else if (decimal.TryParse(attr.Value, out decimalNum))
                        attrib = new Attribute( attr.Name, "double", attr.Value, "attr" );
                    else
                    {
                        attrib = new Attribute( attr.Name, "CATUnicodeString", attr.Value, "attr" );
                    }

                    obj.AddAttribute( attrib );
                }
            }

            if (node.HasChildNodes)
            {
                // Element with attr can have children elements but not text children nodes.
                if (null == obj)
                {
                    obj = new ClassObject( node.Name, null, "element" );
                }

                tab += "\t";
                foreach (XmlNode child in node.ChildNodes)
                {
                    if (child.NodeType == XmlNodeType.Element)
                    {
                       //<channel type="Entertainment">  <== node Object <channel>
                       //  <title>XML.com</title>        <== child node being iterated

                        PrintChildren((XmlElement)child, tab, obj);                        
                    }
                    else if (child.NodeType == XmlNodeType.Text)
                    {
                        // <language>en-us</language> <== node Object <language>
                        // child ==> "en-us"
                        child.Value.Trim();

                        Attribute attr = null;

                        decimal decimalNum = 0;
                        int number1 = 0;
                        if( int.TryParse( child.Value, out number1 ) )
                        {
                            attr = new Attribute( node.Name, "int", child.Value, "text" );
                        }
                        else if( decimal.TryParse( child.Value, out decimalNum ) )
                            attr = new Attribute( node.Name, "double", child.Value, "text" );
                        else
                        {
                            attr = new Attribute( node.Name, "CATUnicodeString", child.Value, "text" );
                        }

                        if( node.HasAttributes )
                        {
                            obj.AddAttribute( attr );
                        }
                        else
                        {   // if element has only text child then add the text as attr to elements parent
                            obj = null;
                            parentClass.AddAttribute( attr );
                        }
                    }
                }
            }

            //if( null != obj )
            //{
            //    obj.RemoveDuplicateChildren();
            //}

            if( null != parentClass )
            {
                // Node with single child are added as Parent Class attribute
                if( null != obj && obj.IsEmpty() )
                {
                    parentClass.Merge( obj );
                }
                else
                {
                    parentClass.AddChild( obj );
                }
            }

            return obj;
        }
    }
}
